package com.yuyou.fn.educational.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.github.wens.mybatisplus.toolkit.IdWorker;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.yuyou.fn.common.constant.JobNatureEnum;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.*;
import com.yuyou.fn.educational.entity.Teacher;
import com.yuyou.fn.educational.mapper.TeacherMapper;
import com.yuyou.fn.educational.service.IBaseGradeService;
import com.yuyou.fn.educational.service.IBaseSubjectService;
import com.yuyou.fn.educational.service.ITeacherService;
import com.yuyou.fn.educational.vo.TeacherQueryVo;
import com.yuyou.fn.educational.vo.TeacherSaveOrUpdateVo;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.platform.service.IAreaTeamService;
import com.yuyou.fn.platform.service.IBusTeamService;
import com.yuyou.fn.platform.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * Teacher 表数据服务层接口实现类
 */
@Service
public class TeacherServiceImpl extends SuperServiceImpl<TeacherMapper, Teacher, Long> implements ITeacherService {

    @Resource
    private IBaseGradeService baseGradeService;

    @Resource
    private IBaseSubjectService baseSubjectService;

    @Resource
    private IAreaTeamService areaTeamService;

    @Resource
    private IBusTeamService busTeamService;


	@Resource
	private ISysUserService sysUserService;

	private LoadingCache<Long,Optional<Teacher>> loadingCacheOfTeacher ;

    @PostConstruct
    public void init(){
        loadingCacheOfTeacher = CacheUtils.buildCache(5,this::findById);
    }


    @Override
    public List<Teacher> findTeacherByBusTeamIdsAndCond( List<Long> busTeamIds,TeacherQueryVo teacherQueryVo) {
        if (busTeamIds==null ||busTeamIds.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<Teacher> example = Teacher.createExample();

        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,teacherQueryVo);
        criteria.andIn("busTeamId",busTeamIds);
        example.orderBy("areaTeamId");
        example.orderBy("busTeamId");
        return findListByExample(example);
    }

    @Transactional
    @Override
    public void saveOrUpdateTeacher(TeacherSaveOrUpdateVo teacherSaveOrUpdateVo) {
        if (StringUtils.isEmpty(teacherSaveOrUpdateVo.getTeachGradeIds())){
            teacherSaveOrUpdateVo.setTeachGradeIds(null);
        }
        if (StringUtils.isEmpty(teacherSaveOrUpdateVo.getTeachSubjectIds())){
            teacherSaveOrUpdateVo.setTeachSubjectIds(null);
        }
        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(teacher, teacherSaveOrUpdateVo);

        fillExtraData(teacher,teacherSaveOrUpdateVo);

        checkTeacher(teacher);

        if (teacher.getTeacherId() == null) {
            teacher.setCreateTime(TimeUtils.now());
            teacher.setUpdateTime(TimeUtils.now());
            teacher.setAuthenticationCode(Utils.to62(IdWorker.getId()));
            insertSelective(teacher);

        } else {
            teacher.setUpdateTime(TimeUtils.now());
            if (teacherSaveOrUpdateVo.getFullChange()!=null && teacherSaveOrUpdateVo.getFullChange()==1){
                updateById(teacher);
            }else {
                updateSelectiveById(teacher);
            }

        }
        if (StringUtils.isNotEmpty(teacherSaveOrUpdateVo.getEmail())){
            sysUserService.createSysUserIfNeed(teacher.getTeacherId(),teacher.getTeacherName(),teacher.getPhoneNo() ,teacher.getEmail() , 3 );
        }
    }



    private void checkTeacher(Teacher teacher) {

		// 验证手机号码、身份证唯一性
        if(StringUtils.isNotEmpty(teacher.getPhoneNo())){
            Example<Teacher> example = Teacher.createExample();
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("areaTeamId",teacher.getAreaTeamId()).
                    andEqualTo("phoneNo", teacher.getPhoneNo()).andNotEqualTo("teacherId",teacher.getTeacherId());
            example.or().andEqualTo("areaTeamId",teacher.getAreaTeamId()).
                    andEqualTo("idNo",teacher.getIdNo()).andNotEqualTo("teacherId",teacher.getTeacherId());
            long l = countByExample(example);
            if (l>0l) throw new BusException("该区域手机号码或身份证已被使用！");
       /*     List<Teacher> teachers = findListByExample(example);
            for (Teacher one : teachers){
                if (one.getAreaTeamId().equals(teacher.getAreaTeamId()) && (one.getPhoneNo().equals(teacher.getPhoneNo())
                        || one.getIdNo().equals(teacher.getIdNo()))){
                    throw new BusException("该区域手机号码或身份证已被使用！");
                }
            }*/
        }

        if(teacher.getAccessType()!=null && teacher.getAccessType() == 1 && teacher.getBusTeamId() == null ){
            throw new BusException("职能选择班主任时，人事单位为必选项");
        }
    /*    if(teacher.getStatus()!=null && teacher.getStatus() == 0 &&   teacher.getDepartureTime()==null ){
            throw new BusException("设置离职离职时间必选");
        }*/


    }

    private void fillExtraData(Teacher teacher,TeacherSaveOrUpdateVo teacherSaveOrUpdateVo) {
        String teachGradeIds = teacher.getTeachGradeIds();
        if (teachGradeIds != null) {
            teacher.setTeachGradeNames(StringUtils.join(baseGradeService.findGradeNameByIds(Utils.toLongIds(teachGradeIds)), ","));
        } else {
            if (teacherSaveOrUpdateVo.getFullChange()!=null && teacherSaveOrUpdateVo.getFullChange()==1){
                teacher.setTeachGradeNames(StringUtils.EMPTY);
            }
        }

        String teachSubjectIds = teacher.getTeachSubjectIds();

        if (teachSubjectIds != null) {
            teacher.setTeachSubjectNames(StringUtils.join(baseSubjectService.findSubjectNameByIds(Utils.toLongIds(teachSubjectIds)), ","));
        } else {
            if (teacherSaveOrUpdateVo.getFullChange()!=null && teacherSaveOrUpdateVo.getFullChange()==1){
                teacher.setTeachSubjectNames(StringUtils.EMPTY);
            }
        }

        if (teacher.getAreaTeamId() != null) {
            teacher.setAreaTeamName(areaTeamService.findTeamNameById(teacher.getAreaTeamId()));
        } else {
            if (teacherSaveOrUpdateVo.getFullChange()!=null && teacherSaveOrUpdateVo.getFullChange()==1){
                teacher.setAreaTeamName(StringUtils.EMPTY);
            }

        }

        if (teacher.getBusTeamId() != null) {
            teacher.setBusTeamName(busTeamService.findTeamNameById(teacher.getBusTeamId()));
        } else {
            if (teacherSaveOrUpdateVo.getFullChange()!=null && teacherSaveOrUpdateVo.getFullChange()==1){
                teacher.setBusTeamName(StringUtils.EMPTY);
            }

        }

    }

    @Override
    public Page<Teacher> findTeacherByQueryForPage(TeacherQueryVo teacherQueryVo, DataPermission dataPermission, int pageNo, int pageSize) {
        Example<Teacher> example = Teacher.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, teacherQueryVo);

        if( dataPermission.getUserType() == 2 ){
            CriteriaUtils.fillConditionForBusPermission(criteria,dataPermission.getBusTeamIds());
        }else{
            CriteriaUtils.fillConditionForAreaTeamPermission(criteria,dataPermission.getAreaTeamIds());
        }

        return findPageByExample(example, pageNo, pageSize);
    }


    @Override
    public Page<Teacher> findTeacherByBusTeamListForPage(TeacherQueryVo teacherQueryVo, List<Long> busTeamIds, int pageNo, int pageSize) {
        Example<Teacher> example = Teacher.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, teacherQueryVo);
        if (Utils.checkListNotEmpty(busTeamIds)){
            criteria.andIn("busTeamId",busTeamIds);
        }
        return findPageByExample(example, pageNo, pageSize);
    }

    @Override
    public Page<Teacher> findTeacherInBusTeamListOrNullForPage(DataPermission dataPermission,TeacherQueryVo teacherQueryVo, List<Long> busTeamIds, int pageNo, int pageSize) {
        Example<Teacher> example = Teacher.createExample();
        example.orderBy("createTime").desc();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria, teacherQueryVo);
        if (Utils.checkListNotEmpty(busTeamIds)){
            criteria.andIn("busTeamId",busTeamIds);
        }

        StringBuffer stringBuffer=new StringBuffer();
        stringBuffer.append("(bus_team_id is null ");
        if (Utils.checkListNotEmpty(dataPermission.getBusTeamIds())){
            stringBuffer.append(" or bus_team_id in ("+StringUtils.join(dataPermission.getBusTeamIds(),',')+")");
        }else {
            throw new BusException("无业务组权限");
        }

        //criteria.in("campusId" , dataPermission.getCampusIds() );
        stringBuffer.append( ")");
        criteria.andCondition(stringBuffer.toString());

        return findPageByExample(example, pageNo, pageSize);
    }

    @Override
    public List<Teacher> findTeacherByQueryForList(TeacherQueryVo teacherQueryVo) {
        Example<Teacher> example = Teacher.createExample();
        example.orderBy("createTime").desc();
        teacherQueryVo.setStatus(1);
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,teacherQueryVo);

        return findListByExample(example);
    }

    @Override
    public void deleteTeacher(Long teacherId) {
        deleteById(teacherId);
    }

    @Override
    public Page<Teacher> findTeacherListForClassArrangement(TeacherQueryVo teacherQueryVo, int pageNo, int pageSize){
        Example<Teacher> example = Teacher.createExample();

        example.orderBy("createTime").desc();
        teacherQueryVo.setStatus(1);
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,teacherQueryVo);
        return findPageByExample(example,pageNo,pageSize);
    }


    @Override
    public Teacher findTeacherByAuthenticationCode(String authenticationCode) {
        Example<Teacher> example = Teacher.createExample();
        example.createCriteria().andEqualTo("authenticationCode",authenticationCode);
        return findOneByExample(example);
    }



	/** 导出老师列表 */
	@Override
	public Workbook exportTeachers(TeacherQueryVo teacherQueryVo, DataPermission dataPermission) {

		Example<Teacher> example = Teacher.createExample();
		example.orderBy("createTime").desc();
		Example.Criteria criteria = example.createCriteria();
		CriteriaUtils.fillCondition(criteria, teacherQueryVo);

		if (dataPermission.getUserType() == 2) {
			CriteriaUtils.fillConditionForBusPermission(criteria, dataPermission.getBusTeamIds());
		} else {
			CriteriaUtils.fillConditionForAreaTeamPermission(criteria, dataPermission.getAreaTeamIds());
		}

		List<Teacher> teacherList = findListByExample(example);
		SXSSFWorkbook teachersExcel = teachers2excel(teacherList);
		return teachersExcel;
	}


	public static SXSSFWorkbook teachers2excel(List<Teacher> teachers) {
		SXSSFWorkbook excel = new SXSSFWorkbook();
		SXSSFSheet sheet = excel.createSheet("teachers");
		SXSSFRow firstRow = sheet.createRow(0);
		String[] titles = new String[] { "姓名", "身份证","任职性质",  "性别",
				"电话号码", "任教年级", "任教科目", "所在区域", "人事关系", "入职时间", "状态","星级","职能" ,"老师头像地址"};

		for (int i = 0; i < titles.length; i++) {
			firstRow.createCell(i).setCellValue(titles[i]);
		}

		for (int i = 0; i < teachers.size(); i++) {
			SXSSFRow row = sheet.createRow(i + 1);
            int cellNum=0;
			Teacher teacher = teachers.get(i);
			SXSSFCell cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getTeacherName());

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getIdNo());

            cell = row.createCell(cellNum++);
            cell.setCellValue(EnumUtils.getName(JobNatureEnum.values() ,teacher.getJobNature()));

	/*		cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getAuthenticationCode());*/

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getSex() == 1 ? "男" : "女");

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getPhoneNo());

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getTeachGradeNames());

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getTeachSubjectNames());

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getAreaTeamName());

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getBusTeamName());

			cell = row.createCell(cellNum++);
			cell.setCellValue(TimeUtils.date2String(teacher.getJoinTime(), " yyyy-MM-dd"));

			cell = row.createCell(cellNum++);
			cell.setCellValue(teacher.getStatus() == 0 ? "离职" : (teacher.getStatus() == 1 ? "在职" : ""));

            cell = row.createCell(cellNum++);
            cell.setCellValue(teacher.getLevel()==null?"":teacher.getLevel().toString());

            cell = row.createCell(cellNum++);
            cell.setCellValue((teacher.getAccessType()!=null && teacher.getAccessType() == 1) ? "班主任" : (teacher.getAccessType() == 0 ? "任课老师" : "外部班主任"));

            cell = row.createCell(cellNum++);
            cell.setCellValue(StringUtils.defaultString(teacher.getAvatarUrl()));

		}
		return excel;
	}

    @Override
    public List<Teacher> findOnJobTeacherByPhoneNo(String phoneNo,Long areaTeamId) {
        Example<Teacher> example = Teacher.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("phoneNo",phoneNo).andEqualTo("status",1);
        if (areaTeamId!=null){
            criteria.andEqualTo("areaTeamId",areaTeamId);
        }
        return findListByExample(example);
    }

    @Override
    public Teacher findTeacherByIdNo(String idNo) {
        Example<Teacher> example = Teacher.createExample();
        example.createCriteria().andEqualTo("idNo",idNo);
        return findOneByExample(example);
    }

    @Override
    public Teacher findTeacherByAreaTeamIdTeacherName(Long areaTeamId, String teacherName) {
        Example<Teacher> example = Teacher.createExample();
        example.createCriteria().andEqualTo("areaTeamId",areaTeamId).andEqualTo("teacherName" , teacherName );
        return findOneByExample(example);
    }

    @Override
    public List<Teacher> findTeacherListByIdNos(List<String> idNos) {
        if (idNos==null || idNos.size()<=0){
            return Collections.EMPTY_LIST;
        }
        Example<Teacher> example = Teacher.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andIn("idNo",idNos);
        return this.findListByExample(example);
    }

    @Override
    public List<Teacher> findListByAreaTeamId(long areaTeamId,String ...columns) {
        Example<Teacher> example = Teacher.createExample();
        Example.Criteria criteria=example.createCriteria();
        criteria.andEqualTo("areaTeamId",areaTeamId).andEqualTo("status",1);
        return this.findListByExample(example);
    }


    @Override
    public String findTeacherNameFromFastCache(Long teacherId) {
        Optional<Teacher> optionalOfTeacher ;
        try {
            optionalOfTeacher = loadingCacheOfTeacher.get(teacherId);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        return optionalOfTeacher.isPresent() ? optionalOfTeacher.get().getTeacherName() : StringUtils.EMPTY ;
    }
}